package common.core.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 日期工具类
 */
public class DateUtil {

    public static String dateString = "yyyy-MM-dd HH:mm:ss";

    public static String dateStringNo = "yyyyMMddHHmmss";

    public static String dateStringDir = "yyyyMMdd";

    public static String str = "yyyy-MM";

    public static String strYYYYMMMDD = "yyyy-MM-dd";

    private static DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
    private static DateFormat dayFormat = new SimpleDateFormat("yy-MM-dd");

    public static ThreadLocal<SimpleDateFormat> threadSDF = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };

    public static ThreadLocal<SimpleDateFormat> threadSB = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };

    /**
     * 日期转字符串
     *
     * @param date
     * @return
     */
    public static String DateToString(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat(dateString);
        String dateString = formatter.format(date);
        return dateString;
    }

    /**
     * 日期转字符串
     *
     * @param date
     * @return
     */
    public static String DToString(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat(strYYYYMMMDD);
        String dateString = formatter.format(date);
        return dateString;
    }

    /**
     * 日期转字符串
     *
     * @param date
     * @return
     */
    public static String FormatDate(String date) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(dateString);
        SimpleDateFormat df = new SimpleDateFormat(str);
        return sdf.format(df.parse(date));
    }

    /**
     * 去掉时分秒，返回年月日yy-MM-dd HH:mm:ss -> yyyy-MM-dd
     *
     * @param date
     * @return yyyy-MM-dd
     * @throws ParseException
     */
    public static String FormatDateStr(String date) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(strYYYYMMMDD);
        SimpleDateFormat df = new SimpleDateFormat(strYYYYMMMDD);
        return sdf.format(df.parse(date));
    }

    /**
     * 日期转字符串
     *
     * @param date
     * @return
     */
    private static final SimpleDateFormat sdf = new SimpleDateFormat(dateString);

    public static Date StringToDate(String date) throws ParseException {
        return DateUtil.threadSDF.get().parse(date);
    }

    /**
     * 返回季度开始结束年月
     *
     * @param
     * @return
     */
    public static List<String> StringToList(String latestTime) {
        List<String> list = Lists.newArrayList();
        String year = latestTime.split("-")[0];
        int month = Integer.parseInt(latestTime.split("-")[1]);
        if (month >= 1 && month <= 3) {
            list.add(year + "-01-01 00:00:00");
            list.add(year + "-02-01 00:00:00");
            list.add(year + "-03-01 00:00:00");
        } else if (month >= 4 && month <= 6) {
            list.add(year + "-04-01 00:00:00");
            list.add(year + "-05-01 00:00:00");
            list.add(year + "-06-01 00:00:00");
        } else if (month >= 7 && month <= 9) {
            list.add(year + "-07-01 00:00:00");
            list.add(year + "-08-01 00:00:00");
            list.add(year + "-09-01 00:00:00");
        } else {
            list.add(year + "-10-01 00:00:00");
            list.add(year + "-11-01 00:00:00");
            list.add(year + "-12-01 00:00:00");
        }
        return list;
    }

    /**
     * 返回月上旬中旬下旬开始结束年月
     *
     * @param
     * @return
     */
    public static Map<String, String> MonthToList(String monthStr, int flag) {
        Map dateMap = Maps.newHashMap();
        List list = Lists.newArrayList();
        list.add("1");
        list.add("3");
        list.add("5");
        list.add("7");
        list.add("8");
        list.add("10");
        list.add("12");
        String year = monthStr.split("-")[0];
        int month = Integer.parseInt(monthStr.split("-")[1]);
        if (flag == 1) {
            dateMap.put("beginDate", year + "-" + month + "-01 00:00:00");
            dateMap.put("endDate", year + "-" + month + "-10 23:59:59");
        }
        if (flag == 2) {
            dateMap.put("beginDate", year + "-" + month + "-11 00:00:00");
            dateMap.put("endDate", year + "-" + month + "-20 23:59:59");
        }
        if (flag == 3) {
            dateMap.put("beginDate", year + "-" + month + "-21 00:00:00");
            if (list.contains(month + "")) {
                dateMap.put("endDate", year + "-" + month + "-31 23:59:59");
            } else {
                if ("2".equals(month + "")) {
                    if ((Integer.parseInt(year) % 4 == 0) && (Integer.parseInt(year) % 100 != 0) || (Integer.parseInt(year) % 400 == 0)) {
                        dateMap.put("endDate", year + "-" + month + "-29 23:59:59");
                    } else {
                        dateMap.put("endDate", year + "-" + month + "-28 23:59:59");
                    }
                } else {
                    dateMap.put("endDate", year + "-" + month + "-30 23:59:59");
                }
            }
        }
        return dateMap;
    }


    /**
     * 获取当前日期时间戳字符串
     *
     * @return
     */
    public static String getCurrentDate() {
        return DateToString(new Date());
    }

    /**
     * 获取当前年
     *
     * @return
     */
    public static String getCurrentYear() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy");
        String dateString = formatter.format(new Date());
        return dateString;
    }

    /**
     * 获取当前日期时间戳字符串
     *
     * @return
     */
    public static String getCurrentTime() {
        return DToString(new Date());
    }


    public static String DateToNo(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat(dateStringNo);
        String dateString = formatter.format(date);
        return dateString;
    }

    public static String getDays() {
        SimpleDateFormat formatter = new SimpleDateFormat(dateStringDir);
        String dateString = formatter.format(new Date());
        return dateString;
    }


    public static long DateStringToLong(String str) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat(dateString);
        Date date = formatter.parse(str);
        return date.getTime();
    }

    public static String DateToDir(Date date) throws ParseException {

        SimpleDateFormat formatter = new SimpleDateFormat(dateStringDir);
        String dateString = formatter.format(date);
        return dateString;
    }

    /**
     * 获取昨天开始时间和结束时间
     *
     * @return
     */
    public static Map getYesterdayRange(String date) throws ParseException {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); // HH:mm:ss
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map condition = Maps.newHashMap();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(df.parse(date));
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        condition.put("endDate", sdf.format(calendar.getTime()));
        calendar.set(Calendar.HOUR_OF_DAY, -24);
        condition.put("startDate", sdf.format(calendar.getTime()));
        return condition;
    }

    /**
     * 获得近一周的开始时间和结束时间
     *
     * @return
     */
    public static Map getDaySevenRange() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map condition = Maps.newHashMap();
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
				0, 0, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 24);
        condition.put("endDate", df.format(calendar.getTime()));
        calendar.set(Calendar.HOUR_OF_DAY, -168);
        condition.put("startDate", df.format(calendar.getTime()));
        return condition;
    }

    /**
     * 获得近一月的开始时间和结束时间
     *
     * @return
     */
    public static Map getDayMonthRange() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map condition = Maps.newHashMap();
        Calendar calendar = Calendar.getInstance();
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
				0, 0, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 24);
        condition.put("endDate", df.format(calendar.getTime()));
        calendar.set(Calendar.HOUR_OF_DAY, -720);
        condition.put("startDate", df.format(calendar.getTime()));
        return condition;
    }

    /**
     * 获得指定日期的前一天
     *
     * @param specifiedDay
     * @return
     */
    public static String getSpecifiedDayBefore(String specifiedDay) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateString);
        Calendar c = Calendar.getInstance();
        Date date = new SimpleDateFormat(dateString).parse(specifiedDay);
        c.setTime(date);
        int day = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day - 1);
        String dayBefore = new SimpleDateFormat(dateString).format(c.getTime());
        return dayBefore;
    }

    /**
     * 获得指定日期的前一天
     *
     * @param specifiedDay
     * @return
     */
    public static String getStrDayBefore(String specifiedDay) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        Date date = new SimpleDateFormat("yyyy-MM-dd").parse(specifiedDay);
        c.setTime(date);
        int day = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day - 1);
        String dayBefore = new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
        return dayBefore;
    }

    /**
     * 获得前一天
     *
     * @return
     */
    public static String getDayBefore() throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        Date date = new Date();
        c.setTime(date);
        int day = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day - 1);
        String dayBefore = simpleDateFormat.format(c.getTime());
        return dayBefore;
    }

    /**
     * 获取给定时间对应的毫秒数
     *
     * @param time "HH:mm:ss"
     * @return
     */
    private static long getTimeMillis(String time) {
        try {
            Date currentDate = dateFormat.parse(dayFormat.format(new Date()) + " " + time);
            return currentDate.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 获取日期范围类的所有日期
     *
     * @param startDate 开始日期
     * @param endDate   结束日期
     * @param dataType  1:天,2:月,3:周
     * @return
     */
    public static List<String> getPerDaysByStartAndEndDate(String startDate, String endDate, int dataType) {

        try {
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            if (dataType == 2) {
                format = new SimpleDateFormat("yyyy-MM");
            }
            Date sDate = format.parse(startDate);
            Date eDate = format.parse(endDate);
            long start = sDate.getTime();
            long end = eDate.getTime();
            if (start > end) return null;
            Calendar calendar = Calendar.getInstance();
            calendar.setFirstDayOfWeek(Calendar.MONDAY);//设置周一是一周的第一天
            calendar.setMinimalDaysInFirstWeek(1);//设置一天也算一周
            calendar.setTime(eDate);
            List<String> res = new ArrayList();
            while (end >= start) {
                if (dataType == 1) {
                    res.add(format.format(calendar.getTime()));
                    calendar.add(Calendar.DAY_OF_MONTH, -1);
                } else if (dataType == 2) {
                    res.add(new SimpleDateFormat("yyyy-MM").format(calendar.getTime()));
                    calendar.add(Calendar.MONTH, -1);
                } else {
                    String weekStr = new SimpleDateFormat("yyyy年第").format(calendar.getTime());
                    weekStr += calendar.get(Calendar.WEEK_OF_YEAR) + "周";
                    res.add(weekStr);
                    int weekdays = calendar.get(Calendar.DAY_OF_WEEK) - 1;
                    weekdays = weekdays == 0 ? 7 : weekdays;
                    calendar.add(Calendar.DAY_OF_MONTH, -weekdays);
                }
                end = calendar.getTimeInMillis();
            }
            Collections.reverse(res);
            return res;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static List<String> getMonthStartAndEndDay(String startDate, String endDate) {
        List<String> months = getPerDaysByStartAndEndDate(startDate, endDate, 2);
        List<String> monthDays = new ArrayList<>();

        for (String item : months) {
            Integer day = getMonthLastDay(item);
            monthDays.add(item + "-01," + item + "-" + day);

        }
        return monthDays;
    }

    /**
     * 获取月份的最后一天
     *
     * @param date
     * @return
     */
    public static Integer getMonthLastDay(String date) {
        try {
            DateFormat format = new SimpleDateFormat("yyyy-MM");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(format.parse(date));
            return calendar.getActualMaximum(5);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 31;
    }

    /**
     * 获取某一年某一周的开始日期
     *
     * @param year
     * @param week
     * @return
     */
    public static String getWeekFirst(int year, int week) {
        try {
            Calendar cal = Calendar.getInstance();
            cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
            cal.set(Calendar.YEAR, year);
            cal.set(Calendar.WEEK_OF_YEAR, week);
            return cal.get(Calendar.YEAR) + "-" + (cal.get(Calendar.MONTH) + 1) + "-" +
                    cal.get(Calendar.DAY_OF_MONTH);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 获取指定日期前后某一天的日期
     *
     * @param date 日期
     * @param day  前后多少天,之前为负数.之后为正数
     * @return
     */
    public static String getOneDay(String date, int day) {
        try {
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(format.parse(date));
            calendar.add(Calendar.DATE, day);
            return format.format(calendar.getTime());
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 获取之前的日期
     *
     * @param date 日期
     * @param date 类型 1:天,2:月,3:周
     */
    public static String getBeforeDate(String date, int dataType) {
        try {
            DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            if (dataType == 2) {
                format = new SimpleDateFormat("yyyy-MM");
            }
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(format.parse(date));
            if (dataType == 1) {
                calendar.add(Calendar.DAY_OF_MONTH, -1);
                return format.format(calendar.getTime());
            }
            if (dataType == 2) {
                calendar.add(Calendar.MONTH, -1);
                return new SimpleDateFormat("yyyy-MM").format(calendar.getTime());
            } else {
                calendar.add(Calendar.DAY_OF_MONTH, -7);
                return format.format(calendar.getTime());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取一个月前的日期
     *
     * @param date
     * @return
     */
    public static String getBeforeMonth(String date) {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(format.parse(date));
            calendar.add(Calendar.MONTH, -1);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            return format.format(calendar.getTime());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取三个月前的日期
     *
     * @return
     */
    public static String getThreeBeforeMonth() {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.MONTH, -3);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            return format.format(calendar.getTime());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     *  获取某段时间内的所有日期
     * @param dStart
     * @param dEnd
     * @return
     */
    public static List<String> findDates(String dStart, String dEnd) {
        try {
            Date start = threadSB.get().parse(dStart);
            Date end = threadSB.get().parse(dEnd);
            Calendar cStart = Calendar.getInstance();
            cStart.setTime(start);
            List dateList = new ArrayList();
            dateList.add(dStart);
            while (end.after(cStart.getTime())) {
                cStart.add(Calendar.DAY_OF_MONTH, 1);
                dateList.add(threadSB.get().format(cStart.getTime()));
            }
            return dateList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
